﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using WpfEncryption.Hash_Algorithm;

namespace WpfEncryption
{
    public static class Encrytion
    {
        public static string EncryptMD5(this string text)
        {
            var hasher = new MD5CryptoServiceProvider();
            var bs = Encoding.UTF8.GetBytes(text);
            bs = hasher.ComputeHash(bs);
            return bs.ConvertToString("x2");
        }

        public static string EncryptFileMD5(this string filename, bool bigSize = false)
        {
            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
                return msg;
            try
            {
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var hash = MD5.Create();
                    var bs = hash.ComputeHash(stream);
                    return bs.ConvertToString("x2");
                }
            }
            catch (Exception exception)
            {
                return exception.Message;
            }

        }

        public static string EncryptSHA1(this string text)
        {
            var hasher = new SHA1CryptoServiceProvider();
            var bs = Encoding.UTF8.GetBytes(text);
            bs = hasher.ComputeHash(bs);
            return bs.ConvertToString("x2");
        }


        public static string EncryptFileSHA1(this string filename, bool bigSize = false)
        {
            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
                return msg;
            try
            {
                byte[] bs;
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var hash = SHA1.Create();
                    bs = hash.ComputeHash(stream);
                }

                return bs.ConvertToString("x2");
            }
            catch (Exception exception)
            {
                return exception.Message;
            }

        }

        public static string EncryptSHA256(this string text)
        {
            var hasher = new SHA256CryptoServiceProvider();
            var bs = Encoding.UTF8.GetBytes(text);
            bs = hasher.ComputeHash(bs);
            return bs.ConvertToString("x2");

        }

        public static string EncryptFileSHA256(this string filename, bool bigSize = false)
        {
            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
            {
                if (msg.Equals("file too larger"))
                {
                    var f = new FileInfo(filename);
                    if (f.Length > Math.Pow(1024, 2) * 300) return "File is larger than 300MB. Checksum is canceled!!!";
                }
                return msg;
            }
            try
            {
                byte[] bs;
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var hash = SHA256.Create();
                    bs = hash.ComputeHash(stream);
                }

                return bs.ConvertToString("x2");
            }
            catch (Exception exception)
            {
                return exception.Message;
            }
        }

        public static string EncryptSHA384(this string text)
        {
            var hasher = new SHA384CryptoServiceProvider();
            var bs = Encoding.UTF8.GetBytes(text);
            bs = hasher.ComputeHash(bs);
            return bs.ConvertToString("x2");

        }

        public static string EncryptFileSHA384(this string filename, bool bigSize = false)
        {
            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
            {
                if (msg.Equals("file too larger"))
                {
                    var f = new FileInfo(filename);
                    if (f.Length > Math.Pow(1024, 2) * 100) return "File is larger than 100MB. Checksum is canceled!!!";
                }

                return msg;
            }


            try
            {
                byte[] bs;
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var hash = SHA384.Create();
                    bs = hash.ComputeHash(stream);
                }

                return bs.ConvertToString("x2");
            }
            catch (Exception exception)
            {
                return exception.Message;
            }
        }

        public static string Encode(this string text)
        {
            var utf32 = new UTF32Encoding();
            var bytes = utf32.GetBytes(text);
            //Encoding.UTF32.GetBytes(
            var sha1 = new SHA1CryptoServiceProvider();
            var md5 = new MD5CryptoServiceProvider();
            var kq = sha1.ComputeHash(bytes);
            var kq2 = md5.ComputeHash(kq);
            return kq2.ConvertToString("x2");
        }

        public static string EncodeFile(this string filename, bool bigSize = false)
        {

            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
                return msg;
            try
            {
                byte[] bs;
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var sha1 = SHA1.Create();
                    bs = sha1.ComputeHash(stream);
                    var md5 = MD5.Create();
                    bs = md5.ComputeHash(bs);
                }

                return bs.ConvertToString("x2");
            }
            catch (Exception exception)
            {
                return exception.Message;
            }
        }


        public static string EncryptCRC32(this string text)
        {
            var hasher = new Crc32();
            var bs = Encoding.UTF8.GetBytes(text);
            bs = hasher.ComputeHash(bs);
            return bs.ConvertToString("x2");
        }


        public static string EncryptFileCRC32(this string filename, bool bigSize = false)
        {
            var msg = string.Empty;
            if (!filename.IsFile(ref msg, bigSize))
                return msg;
            try
            {
                byte[] bs;
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 8192))
                {
                    var crc = new Crc32();
                    bs = crc.ComputeHash(stream);
                }

                return bs.ConvertToString("x2");
            }
            catch (Exception exception)
            {
                return exception.Message;
            }

        }

        public static string ConvertToString(this byte[] bs, string format)
        {
            var s = new StringBuilder();
            foreach (var b in bs)
            {
                s.Append(b.ToString(format));
            }
            return s.ToString();
        }

        public static bool IsFile(this string filename, ref string msg, bool bigSize = false)
        {
            if (string.IsNullOrEmpty(filename) || !File.Exists(filename))
            {
                msg = "It not file";
                return false;
            }

            if (bigSize) return true;

            var f = new FileInfo(filename);
            if (f.Length > Math.Pow(1024, 2) * 5)
            {
                msg = "file too larger";
                return false;
            }

            return true;
        }

        public static string EncryptMD4(this string text)
        {
            var md4 = new MD4();
            return md4.Encrypt(text);
        }


        public static string EncryptNTLM(this string text)
        {
            var ntlm = new NTLM();
            return ntlm.Encrypt(text);
        }

        public static string CheckSum(this string filename, TypeEnc TypeEnc)
        {
            switch (TypeEnc)
            {
                case TypeEnc.MD5:
                    return filename.EncryptFileMD5(true);
                case TypeEnc.SHA1:
                    return filename.EncryptFileSHA1(true);
                case TypeEnc.SHA256:
                    return filename.EncryptFileSHA256(true);
                case TypeEnc.SHA384:
                    return filename.EncryptFileSHA384(true);
                case TypeEnc.SHA1MD5:
                    return filename.EncodeFile(true);
                case TypeEnc.CRC32:
                    return filename.EncryptFileCRC32(true);
                default:
                    return string.Empty;
            }
        }

    }

    public enum TypeEnc
    {
        MD5, SHA1, SHA256, SHA384, SHA1MD5, CRC32
    }

}
